"""
文件名: config.py
描述: 项目配置管理模块

本模块包含以下主要功能：
1. 环境变量配置管理
2. 数据库连接配置
3. Redis缓存配置
4. YouTube API配置
5. 安全认证配置

依赖模块:
   - pydantic_settings: 用于配置管理和验证
   - pydantic: 用于数据验证
   - typing: 用于类型注解

使用示例:
   >>> from src.core.config import get_settings
   >>> settings = get_settings()
   >>> print(settings.database_url)

注意事项:
   - 所有敏感信息必须通过环境变量配置
   - 生产环境和开发环境配置分离
   - 配置变更后需要重启服务

作者: AI助手
创建日期: 2024-06-27
最后修改: 2024-06-27
版本: 1.0.0
"""

import os
from functools import lru_cache
from typing import Optional

from pydantic import Field, field_validator, ValidationInfo
from pydantic_settings import BaseSettings


class Settings(BaseSettings):
    """应用程序配置类"""
    
    # 应用基础配置
    app_name: str = "YouTube订阅管理器"
    app_version: str = "1.0.0"
    debug: bool = Field(default=False, validation_alias="DEBUG")
    
    # 服务器配置
    host: str = Field(default="127.0.0.1", validation_alias="HOST")
    port: int = Field(default=5656, validation_alias="PORT")
    
    # 数据库配置
    database_host: str = Field(default="localhost", validation_alias="DB_HOST")
    database_port: int = Field(default=5432, validation_alias="DB_PORT")
    database_name: str = Field(default="youtube_manager", validation_alias="DB_NAME")
    database_user: str = Field(default="postgres", validation_alias="DB_USER")
    database_password: str = Field(default="", validation_alias="DB_PASSWORD")
    admin_db_user: str = Field(default="postgres", validation_alias="ADMIN_DB_USER")
    admin_db_password: str = Field(default="", validation_alias="ADMIN_DB_PASSWORD")
    database_url: Optional[str] = Field(default=None, validation_alias="DATABASE_URL")

    # Redis配置
    redis_host: str = Field(default="localhost", validation_alias="REDIS_HOST")
    redis_port: int = Field(default=6379, validation_alias="REDIS_PORT")
    redis_db: int = Field(default=0, validation_alias="REDIS_DB")
    redis_password: Optional[str] = Field(default=None, validation_alias="REDIS_PASSWORD")
    redis_url: Optional[str] = Field(default=None, validation_alias="REDIS_URL")
    
    # Celery配置
    celery_broker_db: int = Field(default=10, validation_alias="CELERY_BROKER_DB")
    celery_result_backend_db: int = Field(default=11, validation_alias="CELERY_RESULT_BACKEND_DB")
    
    # YouTube API配置
    youtube_api_key: Optional[str] = Field(default=None, validation_alias="YOUTUBE_API_KEY")
    google_client_id: Optional[str] = Field(default=None, validation_alias="GOOGLE_CLIENT_ID")
    google_client_secret: Optional[str] = Field(default=None, validation_alias="GOOGLE_CLIENT_SECRET")
    google_redirect_uri: str = Field(
        default="http://localhost:5656/auth/callback", 
        validation_alias="GOOGLE_REDIRECT_URI"
    )
    
    # JWT配置
    secret_key: str = Field(default="your-secret-key-change-in-production", validation_alias="SECRET_KEY")
    algorithm: str = Field(default="HS256", validation_alias="ALGORITHM")
    access_token_expire_minutes: int = Field(default=30, validation_alias="ACCESS_TOKEN_EXPIRE_MINUTES")
    
    # 日志配置
    log_level: str = Field(default="INFO", validation_alias="LOG_LEVEL")
    log_format: str = Field(
        default="""<green>{time:YYYY-MM-DD HH:mm:ss}</green> | <level>{level: <8}</level> | <cyan>{name}</cyan>:<cyan>{function}</cyan>:<cyan>{line}</cyan> | <level>{message}</level>""",
        validation_alias="LOG_FORMAT"
    )
    
    # API配置
    api_v1_prefix: str = "/api/v1"
    docs_url: str = "/docs"
    redoc_url: str = "/redoc"
    
    # 缓存配置
    cache_prefix: str = Field(default="youtube_manager", validation_alias="CACHE_PREFIX")
    cache_default_ttl: int = Field(default=300, validation_alias="CACHE_DEFAULT_TTL")
    cache_max_memory: str = Field(default="256mb", validation_alias="CACHE_MAX_MEMORY")
    
    # 性能监控配置
    performance_monitoring_enabled: bool = Field(default=True, validation_alias="PERFORMANCE_MONITORING_ENABLED")
    slow_query_threshold: float = Field(default=1.0, validation_alias="SLOW_QUERY_THRESHOLD")
    
    # 速率限制配置
    rate_limit_enabled: bool = Field(default=True, validation_alias="RATE_LIMIT_ENABLED")
    default_rate_limit: int = Field(default=100, validation_alias="DEFAULT_RATE_LIMIT")
    rate_limit_window: int = Field(default=60, validation_alias="RATE_LIMIT_WINDOW")
    
    @field_validator("database_url", mode='before')
    def assemble_db_connection(cls, v: Optional[str], info: ValidationInfo) -> str:
        """构建数据库连接URL"""
        if isinstance(v, str):
            return v
        values = info.data
        return (
            f"postgresql+asyncpg://{values.get('database_user')}"
            f":{values.get('database_password')}@{values.get('database_host')}"
            f":{values.get('database_port')}/{values.get('database_name')}"
        )
    
    @field_validator("redis_url", mode='before')
    def assemble_redis_connection(cls, v: Optional[str], info: ValidationInfo) -> str:
        """构建Redis连接URL"""
        if isinstance(v, str):
            return v
        
        values = info.data
        auth_part = ""
        if values.get("redis_password"):
            auth_part = f":{values.get('redis_password')}@"
        
        return (
            f"redis://{auth_part}{values.get('redis_host')}"
            f":{values.get('redis_port')}/{values.get('redis_db')}"
        )
    
    @property
    def celery_broker_url(self) -> str:
        """Celery消息代理URL"""
        auth_part = ""
        if self.redis_password:
            auth_part = f":{self.redis_password}@"
        
        return (
            f"redis://{auth_part}{self.redis_host}"
            f":{self.redis_port}/{self.celery_broker_db}"
        )
    
    @property
    def celery_result_backend(self) -> str:
        """Celery结果后端URL"""
        auth_part = ""
        if self.redis_password:
            auth_part = f":{self.redis_password}@"
        
        return (
            f"redis://{auth_part}{self.redis_host}"
            f":{self.redis_port}/{self.celery_result_backend_db}"
        )
    
    class Config:
        env_file = ".env"
        env_file_encoding = "utf-8"
        case_sensitive = True


@lru_cache()
def get_settings() -> Settings:
    """
    获取配置实例（单例模式）
    
    Returns:
        Settings: 配置实例
    """
    return Settings()


# 全局配置实例
settings = get_settings()